#include<func.h>
#include"threadPool.h"
int commandInit(Command_t *pCommand){
    pCommand->commandArr[0] = (char*)malloc(sizeof("cd"));
    memcpy(pCommand->commandArr[0],"cd",sizeof("cd"));
    pCommand->commandArr[1] = (char*)malloc(sizeof("ls"));
    memcpy(pCommand->commandArr[1],"ls",sizeof("ls"));
    pCommand->commandArr[2] = (char*)malloc(sizeof("pwd"));
    memcpy(pCommand->commandArr[2],"pwd",sizeof("pwd"));
    pCommand->commandArr[3] = (char*)malloc(sizeof("puts"));
    memcpy(pCommand->commandArr[3],"puts",sizeof("puts"));
    pCommand->commandArr[4] = (char*)malloc(sizeof("gets"));
    memcpy(pCommand->commandArr[4],"gets",sizeof("gets"));
    pCommand->commandArr[5] = (char*)malloc(sizeof("rm"));
    memcpy(pCommand->commandArr[5],"rm",sizeof("rm"));
    pCommand->commandArr[6] = (char*)malloc(sizeof("mkdir"));
    memcpy(pCommand->commandArr[6],"mkdir",sizeof("mkdir"));
    pCommand->commandArr[7] = (char*)malloc(sizeof("rmdir"));
    memcpy(pCommand->commandArr[7],"rmdir",sizeof("rmdir"));
    pCommand->commandNum = 8;
    return 0;
}

int recvCommand(int netfd,char* command){
    train_t train;
    memset(&train,0,sizeof(train_t));
    int ret = recvn(netfd,&train.length,sizeof(train.length));
    if(ret == 1){
        return -1;
    }
    //printf("train.length = %d",train.length);
    ret = recvn(netfd,command,train.length);
    if(ret == 1){
        return -1;
    }
    //printf("train.data = %s\n",train.data);
    return 0;
}

int getRealPath(pathStack_t* pPathStack,const char* subPath,char* realPath){
    char pwd[4096] = {0};
    char realPwd[4096]={0};
    getCurPath(pPathStack,pwd);
    sprintf(realPwd,"%s/%s",subPath,pwd);
    //printf("realPwd = %s,strlen(realPwd) = %ld\n",realPwd,strlen(realPwd));
    memcpy(realPath,realPwd,strlen(realPwd));
    //printf("realPath = %s,strlen(realPath) = %ld\n",realPath,strlen(realPath));
    return 0;
}

int serverExecCommand(int netfd,pathStack_t* pPathStack,const char* command,const char* username){
    //查看当前工作目录
    //char cwd[1024] = {0};
    //getcwd(cwd,sizeof(cwd));
    //printf("cwd = %s\n",cwd);

    //切分命令和参数
    char tempCommand[4096] = {0};
    memcpy(tempCommand,command,strlen(command));
    char* order;
    char* arguments[1024];
    int arglen;
    arglen = 0;
    char* saveptr;
    char argv[4096] = {0};
    order = strtok_r(tempCommand," ",&saveptr);
    if(order!=NULL){
        ++arglen;
    }
    memcpy(argv,saveptr,strlen(saveptr));
    for(int i=0;i<1024;++i){
        arguments[i] = strtok_r(NULL," ",&saveptr);
        if(arguments[i]==NULL){
            break;
        }
        ++arglen;    
    }
    // 判断是哪一种命令并且执行相应的函数
    if(memcmp("cd",order,strlen(order))==0){
        //printf("cd will execute! netfd = %d\n",netfd);
        serverExecCd(netfd,pPathStack,argv,username);
        return 0;
    }

    if(memcmp("ls",order,strlen(order))==0){
        //printf("ls will execute!\n");
        serverExecLs(netfd,pPathStack,argv,username);
        return 0;
    }
    if(memcmp("pwd",order,strlen(order))==0){
        //printf("pwd will execute!\n");
        serverExecPwd(netfd,pPathStack,username);
        return 0;
    }
    if(memcmp("puts",order,strlen(order))==0){
        //printf("puts will execute!\n");
        serverExecPuts(netfd,pPathStack,argv,username);
        return 0;
    }
    if(memcmp("gets",order,strlen(order))==0){
        //printf("gets will execute!\n");
        serverExecGets(netfd,pPathStack,argv,username);
        return 0;
    }
    if(memcmp("rm",order,strlen(order))==0){
        //printf("rm will execute!\n");
        serverExecRm(netfd,pPathStack,argv,username);
        return 0;
    }
    if(memcmp("mkdir",order,strlen(order))==0){
        //printf("mkdir will execute!\n");
        serverExecMkdir(netfd,pPathStack,argv,username);

        return 0;
    }
    if(memcmp("rmdir",order,strlen(order))==0){
        //printf("rmdir will execute!\n");
        serverExecRmdir(netfd,pPathStack,argv,username);

        return 0;
    }
    if(memcmp("reminder",order,strlen(order))==0){
        serverExecPwd(netfd,pPathStack,username);
        return 0;
    }
    if(memcmp("putsBF",order,strlen(order))==0){
        serverPutsBigFile(netfd,pPathStack,argv,username);
        return 0;
    }
    if(memcmp("getsBF",order,strlen(order))==0){
        serverGetsBigFile(netfd,pPathStack,argv,username);
        return 0;
    }
    
   return 1;
} 

int serverExecCd(int netfd,pathStack_t* pPathStack,const char* dirName,const char* username){
    //printf("I am serverExecCd,dirName = %s\n",dirName);
    // 分割文件路径
    char tempDirName[4096] = {0};
    memcpy(tempDirName,dirName,strlen(dirName));
    char* arguments[1024];
    int arglen;
    arglen = 0;
    char* saveptr;
    arguments[0] = strtok_r(tempDirName,"/",&saveptr);
    if(arguments[0]!=NULL){
        ++arglen;
    }
    for(int i=1;i<1024;++i){
        arguments[i] = strtok_r(NULL,"/",&saveptr);
        if(arguments[i]==NULL){
            break;
        }
        ++arglen;    
    }

    ////获取目标文件夹的路径
    //char realPath[4096]={0};
    //char targetPath[4096] ={0};
    //getRealPath(pPathStack,"/home/ahau/netDisk/zhangSan",realPath);
    //sprintf(targetPath,"%s%s",realPath,dirName);
    //    //printf("targetPath = %s\n",targetPath);

    ////初步判断目标文件夹是否存在
    //train_t train;
    //int dirExist = 1;
    //DIR* pdirent = opendir(targetPath);
    ////perror("opendir:");
    //if(pdirent == NULL){
    //    dirExist = 0;
    //}
    ////printf("dirExist = %d\n",dirExist);
    //closedir(pdirent);

    int dirExist = verdictTargetFile(pPathStack,dirName,0,username);
    train_t train;
    // 目标文件夹不存在，通知客户端
    if(dirExist == -1){
        // printf("target Dir not exist!\n");
        memset(&train,0,sizeof(train_t));
        memcpy(train.data,"-1",strlen("-1"));
        train.length = strlen("-1");
        send(netfd,&train.length,sizeof(train.length),0);
        send(netfd,train.data,train.length,0);
        return -1;
    }
    // 进行切换
    for(int i=0;i<1024;i++){
        if(arguments[i]==NULL){
            break;
        }
        if(memcmp(arguments[i],"..",strlen(".."))==0){
            if(pPathStack->pFront == NULL){     //该路径下的文件夹不存在
                dirExist = -1;
                break;
            }
            //出栈
            popPathStack(pPathStack);
        }
        if(memcmp(arguments[i],".",strlen("."))==0){
            continue;
        }
        //入栈
        pushPathStack(pPathStack,arguments[i]);
    }
    
    //查看栈中的路径
    //char curPath[4096] = {0};
    //getCurPath(pPathStack,curPath);
    //printf("curPath = %s\n",curPath);

    // 目标文件夹不存在，通知客户端
    if(dirExist == -1){
        // printf("target Dir not exist!\n");
        memset(&train,0,sizeof(train_t));
        memcpy(train.data,"-1",strlen("-1"));
        train.length = strlen("-1");
        send(netfd,&train.length,sizeof(train.length),0);
        send(netfd,train.data,train.length,0);
        return -1;
    }
    
    //切换成功，通知客户端
    memset(&train,0,sizeof(train_t));
    memcpy(train.data,"0",strlen("0"));
    train.length = strlen("0");
    send(netfd,&train.length,sizeof(train.length),0);
    send(netfd,train.data,train.length,0);
    return 0;
}

int serverExecLs(int netfd,pathStack_t* pPathStack,char* dirName,const char* username){
    //printf("I am serverExecLs,dirName = %s\n",dirName);
    //获取目标文件夹的路径
    char realPath[4096]={0};
    char targetPath[4096] ={0};
    char userDisk[256] = {0};
    sprintf(userDisk,"%s/%s","netDisk",username);
    getRealPath(pPathStack,userDisk,realPath);
    sprintf(targetPath,"%s%s",realPath,dirName);
        //printf("targetPath = %s\n",targetPath);

    ////判断目标文件夹是否存在
    //int dirExist = 1;
    //DIR* pdir = opendir(targetPath);
    ////perror("opendir:");
    //if(pdir == NULL){
    //    closedir(pdir);
    //    dirExist = 0;
    //}
    ////printf("dirExist=%d\n",dirExist);
    ////确保是自己目录下的文件
    //int stackDeep = 0;
    //pathStackNode_t* pCur = pPathStack->pFront;
    //while(1){
    //    if(pCur == NULL){
    //        break;
    //    }
    //    pCur = pCur->pNext;
    //    stackDeep++;
    //}
    ////printf("1.stackDeep = %d\n",stackDeep);
    //
    ////切割要显示的文件路径
    //char tempDirName[4096] = {0};
    //memcpy(tempDirName,dirName,strlen(dirName));
    //char* arguments[1024];
    //int arglen;
    //arglen = 0;
    //char* saveptr;
    //arguments[0] = strtok_r(tempDirName,"/",&saveptr);
    //if(arguments[0]!=NULL){
    //    ++arglen;
    //}
    //for(int i=1;i<1024;++i){
    //    arguments[i] = strtok_r(NULL,"/",&saveptr);
    //    if(arguments[i]==NULL){
    //        break;
    //    }
    //    ++arglen;    
    //}
    //for(int i=0;i<arglen;++i){
    //    if(arguments[i]==NULL){
    //        break;
    //    }
    //    if(memcmp(arguments[i],"..",sizeof(".."))==0){
    //        stackDeep--;
    //        continue;
    //    }
    //    if(memcmp(arguments[i],".",sizeof("."))==0){
    //        continue;
    //    }
    //    stackDeep++;
    //}
    //if(stackDeep<0){
    //    dirExist = 0;
    //}
    // 目标文件夹不存在，通知客户端
    
    int dirExist = 0;
    dirExist = verdictTargetFile(pPathStack,dirName,0,username);
    //printf("dirExist = %d\n",dirExist);
    train_t train;
    if(dirExist == -1){
        // printf("target Dir not exist!\n");
        memset(&train,0,sizeof(train_t));
        memcpy(train.data,"-1",strlen("-1"));
        train.length = strlen("-1");
        send(netfd,&train.length,sizeof(train.length),0);
        send(netfd,train.data,train.length,0);
        return -1;
    }
    
    DIR* pdir = opendir(targetPath);
    //perror("opendir");
    struct dirent* pdirent;
    char fInfo[4096] = {0};
    char tempFInfo[4096] = {0};
    while(1){
        pdirent = readdir(pdir);
        if(pdirent == NULL){
            break;
        }
        if(memcmp(pdirent->d_name,"..",sizeof(".."))==0||memcmp(pdirent->d_name,".",sizeof("."))==0){
            continue;
        }
        memset(fInfo,0,sizeof(fInfo));
        //文件类型
        if(pdirent->d_type == DT_DIR){
            sprintf(fInfo,"-D");
        }else{
            sprintf(fInfo,"-F");
        }
        //文件名
        memset(tempFInfo,0,sizeof(tempFInfo));
        sprintf(tempFInfo,"%s\t\t%s",fInfo,pdirent->d_name);
        memcpy(fInfo,tempFInfo,sizeof(tempFInfo));
        //文件大小
        struct stat statbuf;
        //获得完整路径名
        char filePathname[4096] = {0};
        sprintf(filePathname,"%s/%s",targetPath,pdirent->d_name);
        //printf("filePathname = %s\n",filePathname);
        stat(filePathname,&statbuf);
        char filesize[256] = {0};
        sprintf(filesize,"%ldB",statbuf.st_size);
        memset(tempFInfo,0,sizeof(tempFInfo));
        sprintf(tempFInfo,"%s\t\t\t\t%s\n",fInfo,filesize);
        //printf("pdirent->d_reclen =%ld,fileszie =%sB\n",statbuf.st_size,filesize);
        memcpy(fInfo,tempFInfo,sizeof(tempFInfo));
        
        //将文件的信息发送给客户端
        //printf("%s",fInfo);
        memset(&train,0,sizeof(train_t));
        train.length = strlen(fInfo);
        memcpy(train.data,fInfo,train.length);
        send(netfd,&train.length,sizeof(train.length),0);
        send(netfd,train.data,train.length,0);
    }
    closedir(pdir);

    // 文件信息发送完毕，发送结束标志
    memset(&train,0,sizeof(train_t));
    train.length = 0;
    memcpy(train.data,"",train.length);
    send(netfd,&train.length,sizeof(train.length),0);
    send(netfd,train.data,train.length,0);
    
    return 0;
}

int serverExecPwd(int netfd,pathStack_t* pPathStack,const char* username){
    //printf("I am serverExecPwd\n");
    //获取当前路径
    char curPath[4096] = {0};
    getCurPath(pPathStack,curPath);
    //printf("curPath = %s\n",curPath);
    //发送给客户端
    train_t train;
    memset(&train,0,sizeof(train_t));
    train.length = strlen(curPath);
    memcpy(train.data,curPath,train.length);
    send(netfd,&train.length,sizeof(train.length),0);
    send(netfd,train.data,train.length,0);

    return 0;
}

int serverExecPuts(int netfd,pathStack_t* pPathStack,const char* filename,const char* username){
    //printf("I am serverExecPuts,filename = %s\n",filename);
    //获得要接受文件的名字
    char tempFilename[4096] = {0};
    memcpy(tempFilename,filename,strlen(filename));
    //切割要显示的文件路径
    char* arguments[1024];
    int arglen;
    arglen = 0;
    char* saveptr;
    arguments[0] = strtok_r(tempFilename,"/",&saveptr);
    if(arguments[0]!=NULL){
        ++arglen;
    }
    for(int i=1;i<1024;++i){
        arguments[i] = strtok_r(NULL,"/",&saveptr);
        if(arguments[i]==NULL){
            break;
        }
        ++arglen;    
    }
    char storeFilename[1024]={0};
    memcpy(storeFilename,arguments[arglen-1],strlen(arguments[arglen-1]));
    
    //获得应该存储的文件名
    //char storePathname[4096] = {0};
    //char pwd[4096] ={0};
    //getRealPath(pPathStack,"/home/ahau/netDisk/zhangSan",pwd);
    //sprintf(storePathname,"%s%s",pwd,storeFilename);
    //printf("storeFilename = %s,storePathname = %s\n",storeFilename,storePathname);
    
    //获得当前目录的路径
    char pwd[4096] = {0};
    char userDisk[256] = {0};
    sprintf(userDisk,"%s/%s","netDisk",username);
    getRealPath(pPathStack,userDisk,pwd);
    
        //char cwd[1024] = {0};
        //getcwd(cwd,sizeof(cwd));
        //printf("before chdir ,cwd = %s\n",cwd);
    //改变当前的工作路径
    chdir(pwd);
        //memset(cwd,0,1024);
        //getcwd(cwd,sizeof(cwd));
        //printf("after chdir ,cwd = %s\n",cwd);
    
    //获取栈的深度
    pathStackNode_t* pCur = pPathStack->pFront;
    int stackDeep = 0;
    while(1){
        if(pCur == NULL){
            break;
        }
        stackDeep++;
        pCur = pCur->pNext;
    }
    //printf("stackDeep = %d\n",stackDeep);
    
    //-------------------------------------接收文件----------------------------------------------
    //判断文件能否正常打开
    train_t train;
    memset(&train,0,sizeof(train_t));
    recvn(netfd,&train.length,sizeof(train.length));
    recvn(netfd,train.data,train.length);
    if(memcmp(train.data,"-1",train.length)==0){
        //printf("file don't exist\n");
        for(int i=0;i<stackDeep+2;++i){
            chdir("..");
        }
        return -1;
    }
    //接受文件大小
    off_t filesize;
    memcpy(&filesize,(off_t *)train.data,train.length);
    //printf("filesize = %ld\n",filesize);
    int fd = open(storeFilename,O_RDWR|O_CREAT,0666);
    ftruncate(fd,filesize);
    //printf("filesize = %ld,fd = %d\n",filesize,fd);
    while(1){
        memset(&train,0,sizeof(train_t));
        ssize_t sret = recvn(netfd,&train.length,sizeof(train.length));
        if(sret == 1){
            break;
        }
        sret = recvn(netfd,train.data,train.length);
        if(train.length==0){
            //printf("train.length = %d\n",train.length);
            break;
        }
        //printf("train.data = %s,train.length = %d\n",train.data,train.length);
        write(fd,train.data,train.length);   
    }
    close(fd);
    for(int i=0;i<stackDeep+2;++i){
        chdir("..");
    }
    memset(&train,0,sizeof(train_t));
    train.length = strlen("-1");
    memcpy(train.data,"-1",train.length);
    send(netfd,&train.length,sizeof(train.length),0);
    send(netfd,train.data,train.length,0);
    return 0;
}

int serverExecGets(int netfd,pathStack_t* pPathStack,const char* filename,const char* username){
    //printf("I am serverExecGets,filename = %s\n",filename);
    
    //判断文件是否存在
    char realPath[4096]={0};
    char userDisk[256] = {0};
    sprintf(userDisk,"%s/%s","netDisk",username);
    getRealPath(pPathStack,userDisk,realPath);
    char realFilename[4096]={0};
    sprintf(realFilename,"%s%s",realPath,filename);
    //printf("realFilename=%s\n",realFilename);

    train_t train;
    int fd = open(realFilename,O_RDWR);
    if(fd == -1){
        memset(&train,0,sizeof(train_t));
        train.length = strlen("-1");
        memcpy(train.data,"-1",train.length);
        send(netfd,&train.length,sizeof(train.length),0);
        send(netfd,train.data,train.length,0);
        return -1;
    }
    //fd != -1
    struct stat statbuf;
    fstat(fd,&statbuf);
    off_t filesize = statbuf.st_size;
    memset(&train,0,sizeof(train_t));
    train.length = sizeof(off_t);
    memcpy(train.data,&filesize,train.length);
    send(netfd,&train.length,sizeof(train.length),0);
    send(netfd,train.data,train.length,0);

    while(1){
        memset(&train,0,sizeof(train_t));
        ssize_t sret = read(fd,train.data,sizeof(train.data));
        if(sret == 0){
            close(fd);
            train.length = strlen("0");
            memcpy(train.data,"0",strlen("0"));
            send(netfd,&train.length,sizeof(train.length),0);
            send(netfd,train.data,train.length,0);
            break;
        }
        train.length = sret;
        send(netfd,&train.length,sizeof(train.length),0);
        send(netfd,train.data,train.length,0);
        //printf("send train.data = %s\n",train.data);
    }
    close(fd);
    //接收客户端返回的成功信息
    memset(&train,0,sizeof(train_t));
    recvn(netfd,&train.length,sizeof(train.length));
    recvn(netfd,train.data,train.length);
    //printf("train.data = %s\n",train.data);
    if(memcmp(train.data,"0",strlen("0"))==0){
        //printf("Success!\n");
        return 0;
    }
    return 0;
}

int serverExecRm(int netfd,pathStack_t * pPathStack,const char* filename,const char* username){
    //printf("I am serverExecRm,filename = %s\n",filename);
    int dirExist = verdictTargetFile(pPathStack,filename,1,username);
    //printf("dirExist = %d\n",dirExist);
    train_t train;
    //如果文件对应的目录不存在，通知客户端
    if(dirExist == -1){
        memset(&train,0,sizeof(train_t));
        memcpy(train.data,"-1",sizeof("-1"));
        train.length = sizeof(train.length);
        send(netfd,&train.length,sizeof(train.length),0);
        send(netfd,train.data,train.length,0);
        return -1;
    }
    //如果文件对应的目录存在，但是文件不存在通知客户端
    //获取目标文件夹的路径
    char realPath[4096]={0};
    char targetPath[4096] ={0};
    char userDisk[256] = {0};
    sprintf(userDisk,"%s/%s","netDisk",username);
    getRealPath(pPathStack,userDisk,realPath);
    sprintf(targetPath,"%s%s",realPath,filename);
    int fileExist = access(targetPath,F_OK);
    if(fileExist == 0){
        //删除文件
        int deleteStatus = unlink(targetPath);
        if(deleteStatus == 0){
            memset(&train,0,sizeof(train_t));
            memcpy(train.data,"0",sizeof("0"));
            train.length = sizeof(train.length);
            send(netfd,&train.length,sizeof(train.length),0);
            send(netfd,train.data,train.length,0);
            return 0;
        }
    }
    //文件不存在或者删除失败，通知客户端
    memset(&train,0,sizeof(train_t));
    memcpy(train.data,"-1",sizeof("-1"));
    train.length = sizeof(train.length);
    send(netfd,&train.length,sizeof(train.length),0);
    send(netfd,train.data,train.length,0);
    return -1;
}

int serverExecMkdir(int netfd,pathStack_t* pPathStack,const char* dirpath,const char* username){
    //printf("I am serverExecMkdir,dirpath = %s\n",dirpath);
    //判断要创建的文件夹是不是在自己用户的文件夹
    //确保是自己目录下的文件
    int stackDeep = 0;
    pathStackNode_t* pCur = pPathStack->pFront;
    while(1){
        if(pCur == NULL){
            break;
        }
        pCur = pCur->pNext;
        stackDeep++;
    }
    //切割要显示的文件路径
    int dirExist = 0;  //0表示存在，-1表示不存在
    char tempDirName[4096] = {0};
    memcpy(tempDirName,dirpath,strlen(dirpath));
    char* arguments[1024];
    int arglen;
    arglen = 0;
    char* saveptr;
    arguments[0] = strtok_r(tempDirName,"/",&saveptr);
    if(arguments[0]!=NULL){
        ++arglen;
    }
    for(int i=1;i<1024;++i){
        arguments[i] = strtok_r(NULL,"/",&saveptr);
        if(arguments[i]==NULL){
            break;
        }
        ++arglen;    
    }
    for(int i=0;i<arglen;++i){
        if(arguments[i]==NULL){
            break;
        }
        if(memcmp(arguments[i],"..",sizeof(".."))==0){
            stackDeep--;
            if(stackDeep<0){
                dirExist = -1;
                break;
            }
            continue;
        }
        if(memcmp(arguments[i],".",sizeof("."))==0){
            continue;
        }
        stackDeep++;
    }
    if(stackDeep<0){
        dirExist = -1;
    }

    //文件夹在自己目录下
    //获取目标或者文件的路径
    char realPath[4096]={0};
    char targetPath[4096] ={0};
    char userDisk[256] = {0};
    sprintf(userDisk,"%s/%s","netDisk",username);
    getRealPath(pPathStack,userDisk,realPath);
    sprintf(targetPath,"%s%s",realPath,dirpath);
    
    train_t train;
    if(dirExist==0){
        int mkStatus = mkdir(targetPath,0777);
        if(mkStatus == 0){
            // 创建成功
            memset(&train,0,sizeof(train_t));
            memcpy(train.data,"0",sizeof("0"));
            train.length = sizeof(train.length);
            send(netfd,&train.length,sizeof(train.length),0);
            send(netfd,train.data,train.length,0);
            return 0;
        }
    }
    //文件夹不在自己目录下或者创建失败
    memset(&train,0,sizeof(train_t));
    memcpy(train.data,"-1",sizeof("-1"));
    train.length = sizeof(train.length);
    send(netfd,&train.length,sizeof(train.length),0);
    send(netfd,train.data,train.length,0);
    return 0;
}

int serverExecRmdir(int netfd,pathStack_t* pPathStack,const char* dirpath,const char* username){
    //printf("I am serverExecRmdir,dirpath = %s\n",dirpath);
    //dirpath中不能包含.和..
    int pathIsIllegal = 0; //1表示非法
    char tempDirpath[4096] = {0};
    memcpy(tempDirpath,dirpath,strlen(dirpath));
    char* arguments[1024];
    char* saveptr;
    arguments[0] = strtok_r(tempDirpath,"/",&saveptr);
    if(memcmp(arguments[0],"..",sizeof(".."))==0){
        pathIsIllegal = 1;
    }
    for(int i=1;i<1024;++i){
        arguments[i] = strtok_r(NULL,"/",&saveptr);
        if(memcmp(arguments[0],"..",sizeof(".."))==0 || memcmp(arguments[0],".",sizeof("."))==0){
            pathIsIllegal = 1;
            break;
        }
        if(arguments[i]==NULL){
            break;
        }
    }
    
    train_t train;
    //路径非法，通知客户端
    if(pathIsIllegal == 1){     
        memset(&train,0,sizeof(train_t));
        memcpy(train.data,"1",sizeof("1"));
        train.length = sizeof(train.length);
        send(netfd,&train.length,sizeof(train.length),0);
        send(netfd,train.data,train.length,0);
        return -1;
    }
    //获取目标目录的路径
    char realPath[4096]={0};
    char targetPath[4096] ={0};
    char userDisk[256] = {0};
    sprintf(userDisk,"%s/%s","netDisk",username);
    getRealPath(pPathStack,userDisk,realPath);
    sprintf(targetPath,"%s%s",realPath,dirpath);
    //递归删除文件夹
    int ret = deleteDir(targetPath);
    //删除成功，通知客服端
    if(ret == 0){
        memset(&train,0,sizeof(train_t));
        memcpy(train.data,"0",sizeof("0"));
        train.length = sizeof(train.length);
        send(netfd,&train.length,sizeof(train.length),0);
        send(netfd,train.data,train.length,0);
        return 0;
    }
    //删除失败，通知客户端
    memset(&train,0,sizeof(train_t));
    memcpy(train.data,"2",sizeof("2"));
    train.length = sizeof(train.length);
    send(netfd,&train.length,sizeof(train.length),0);
    send(netfd,train.data,train.length,0);
    return 0;
}

int serverPutsBigFile(int netfd,pathStack_t* pPathStack,const char* filename,const char* username){
    //printf("i am putBigFile\n");
    //获得要接受文件的名字
    char tempFilename[4096] = {0};
    memcpy(tempFilename,filename,strlen(filename));
    //切割要显示的文件路径
    char* arguments[1024];
    int arglen;
    arglen = 0;
    char* saveptr;
    arguments[0] = strtok_r(tempFilename,"/",&saveptr);
    if(arguments[0]!=NULL){
        ++arglen;
    }
    for(int i=1;i<1024;++i){
        arguments[i] = strtok_r(NULL,"/",&saveptr);
        if(arguments[i]==NULL){
            break;
        }
        ++arglen;    
    }
    char storeFilename[1024]={0};
    memcpy(storeFilename,arguments[arglen-1],strlen(arguments[arglen-1]));
    
    //获得当前目录的路径
    char pwd[4096] = {0};
    char userDisk[256] = {0};
    sprintf(userDisk,"%s/%s","netDisk",username);
    getRealPath(pPathStack,userDisk,pwd);
    
    //改变当前的工作路径
    chdir(pwd);
    
    //获取栈的深度
    pathStackNode_t* pCur = pPathStack->pFront;
    int stackDeep = 0;
    while(1){
        if(pCur == NULL){
            break;
        }
        stackDeep++;
        pCur = pCur->pNext;
    }
    
    //-------------------------------------接收大文件----------------------------------------------
    //判断文件能否正常打开
    train_t train;
    memset(&train,0,sizeof(train_t));
    recvn(netfd,&train.length,sizeof(train.length));
    recvn(netfd,train.data,train.length);
    if(memcmp(train.data,"-1",train.length)==0){
        //printf("file don't exist\n");
        for(int i=0;i<stackDeep+2;++i){
            chdir("..");
        }
        return -1;
    }
    //接受文件大小
    off_t filesize;
    off_t lastTotal = 0;
    off_t total = 0;
    memcpy(&filesize,(off_t *)train.data,train.length);
    //printf("filesize = %ld\n",filesize);
    int fd = open(storeFilename,O_RDWR|O_CREAT,0666);
    ftruncate(fd,filesize);
    //printf("filesize = %ld,fd = %d\n",filesize,fd);
    while(1){
        char buf[40960] = {0};
        //printf("lastTotal = %ld\n",lastTotal);
        if(filesize - lastTotal >= 40960){
            int ret = recvn(netfd,buf,40960);
            if(ret == 1){
                //接收失败，通知客户端
                memset(&train,0,sizeof(train_t));
                train.length = strlen("-1");
                memcpy(train.data,"-1",train.length);
                send(netfd,&train.length,sizeof(train.length),0);
                send(netfd,&train.data,train.length,0);
                return -1;
            }
            write(fd,buf,40960);
            total += 40960;
        }
        if(filesize - lastTotal == 0){
            break;
        }
        if(filesize - lastTotal < 40960){
            recvn(netfd,buf,filesize - lastTotal);
            write(fd,buf,filesize - lastTotal);
            total += filesize - lastTotal;
        }
        lastTotal = total;
        //本次接收成功将上传进度发送给客户端
        memset(&train,0,sizeof(train_t));
        char message[1024];
        sprintf(message,"%6.2lf%%",lastTotal*100.0/filesize);
        train.length = strlen(message);
        memcpy(train.data,message,train.length);
        send(netfd,&train.length,sizeof(train.length),0);
        send(netfd,train.data,train.length,0);
    }
    close(fd);
    for(int i=0;i<stackDeep+2;++i){
        chdir("..");
    }
    memset(&train,0,sizeof(train_t));
    train.length = strlen("0");
    memcpy(train.data,"0",train.length);
    send(netfd,&train.length,sizeof(train.length),MSG_NOSIGNAL);
    send(netfd,train.data,train.length,MSG_NOSIGNAL);
    //printf("putsBF end!\n");
    return 0;
}
int serverGetsBigFile(int netfd,pathStack_t* pPathStack,const char* filename,const char* username){
    //printf("i am getsBigFile\n");
    //判断文件是否存在
    char realPath[4096]={0};
    char userDisk[256] = {0};
    sprintf(userDisk,"%s/%s","netDisk",username);
    getRealPath(pPathStack,userDisk,realPath);
    char realFilename[4096]={0};
    sprintf(realFilename,"%s%s",realPath,filename);
    //printf("realFilename=%s\n",realFilename);

    train_t train;
    int fd = open(realFilename,O_RDWR);
    if(fd == -1){
        memset(&train,0,sizeof(train_t));
        train.length = strlen("-1");
        memcpy(train.data,"-1",train.length);
        send(netfd,&train.length,sizeof(train.length),0);
        send(netfd,train.data,train.length,0);
        return -1;
    }
    //fd != -1
    struct stat statbuf;
    fstat(fd,&statbuf);
    off_t filesize = statbuf.st_size;
    memset(&train,0,sizeof(train_t));
    train.length = sizeof(off_t);
    memcpy(train.data,&filesize,train.length);
    send(netfd,&train.length,sizeof(train.length),0);
    send(netfd,train.data,train.length,0);

    //接收客服端已存在的长度
    off_t existLength;
    memset(&train,0,sizeof(train_t));
    recvn(netfd,&train.length,sizeof(train.length));
    recvn(netfd,train.data,train.length);
    memcpy(&existLength,train.data,train.length);
    //printf("existLength = %ld\n",existLength);

    off_t allocateSize = (((filesize)/4096)+1)*4096;
    char* pmmap = (char *)mmap(NULL,allocateSize,PROT_WRITE|PROT_READ,MAP_SHARED,fd,0);
    send(netfd,pmmap+existLength,filesize-existLength,MSG_NOSIGNAL);

    //接收客户端返回的成功信息
    memset(&train,0,sizeof(train_t));
    recvn(netfd,&train.length,sizeof(train.length));
    recvn(netfd,train.data,train.length);
    //printf("train.data = %s\n",train.data);
    if(memcmp(train.data,"0",strlen("0"))==0){
        //printf("Success!\n");
        return 0;
    }
    if(memcmp(train.data,"-1",strlen("-1"))==0){
        //printf("Success!\n");
        return -1;
    }
    return 0;
}


int verdictTargetFile(pathStack_t* pPathStack,const char* pathname,int flag,const char* username){
    //得到用户的目录路径(虚拟路径)
    char tempPathname[4096] = {0};
    memcpy(tempPathname,pathname,strlen(pathname));
    int pathLength = 0;
    if(flag == 1){
        for(unsigned int i=0;i<strlen(tempPathname);i++){
            if(tempPathname[i]=='/'){
                pathLength = i;
            }
        }
    }else{
        pathLength = strlen(pathname);
    }
    
    char dirpath[4096] = {0};
    memcpy(dirpath,tempPathname,pathLength);

    //获取目标或者文件的路径
    char realPath[4096]={0};
    char targetPath[4096] ={0};
    char userDisk[256] = {0};
    sprintf(userDisk,"%s/%s","netDisk",username);
    getRealPath(pPathStack,userDisk,realPath);
    sprintf(targetPath,"%s%s",realPath,dirpath);
    //判断目标文件夹是否存在
    int dirExist = 0;
    DIR* pdir = opendir(targetPath);
    //perror("opendir:");
    if(pdir == NULL){
        closedir(pdir);
        dirExist = -1;
    }
    //printf("dirExist=%d\n",dirExist);
    //确保是自己目录下的文件
    int stackDeep = 0;
    pathStackNode_t* pCur = pPathStack->pFront;
    while(1){
        if(pCur == NULL){
            break;
        }
        pCur = pCur->pNext;
        stackDeep++;
    }
    //printf("1.stackDeep = %d\n",stackDeep);
    
    //切割要显示的文件路径
    char tempDirName[4096] = {0};
    memcpy(tempDirName,dirpath,strlen(dirpath));
    char* arguments[1024];
    int arglen;
    arglen = 0;
    char* saveptr;
    arguments[0] = strtok_r(tempDirName,"/",&saveptr);
    if(arguments[0]!=NULL){
        ++arglen;
    }
    for(int i=1;i<1024;++i){
        arguments[i] = strtok_r(NULL,"/",&saveptr);
        if(arguments[i]==NULL){
            break;
        }
        ++arglen;    
    }
    for(int i=0;i<arglen;++i){
        if(arguments[i]==NULL){
            break;
        }
        if(memcmp(arguments[i],"..",sizeof(".."))==0){
            stackDeep--;
            if(stackDeep<0){
                dirExist = -1;
                break;
            }
            continue;
        }
        if(memcmp(arguments[i],".",sizeof("."))==0){
            continue;
        }
        stackDeep++;
    }
    if(stackDeep<0){
        dirExist = -1;
    }
    return dirExist;
}

int deleteDir(const char* path) {
    DIR* pdir = opendir(path);
    if(pdir == NULL){
        return -1;
    }
    // 遍历目录流，依次删除每一个目录项
    errno = 0;
    struct dirent* pdirent;
    while ((pdirent = readdir(pdir)) != NULL) {
        // 忽略.和..
        const char* name = pdirent->d_name;
        if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0) {
            continue;
        }

        // 拼接路径
        char subpath[256];
        sprintf(subpath, "%s/%s", path, name);

        if (pdirent->d_type == DT_DIR) {
            int ret = deleteDir(subpath);
            if(ret == -1){
                return -1;
            }
        } else {
            int ret = unlink(subpath);
            if(ret == -1){
                return -1;
            }
        }
    }
    // 目录为空了，可以删除该目录了
    int ret = rmdir(path);
    if(ret == -1){
        return -1;
    }

    if(errno) {
        perror("readdir");
        return -1;
    }

    closedir(pdir);
    return 0;
}

